﻿#include "ModbusPDU.h"
#include <iostream>
#define NDEBUG
#include < assert.h >
using namespace std;

#define MODBUSTCPPROTOCOL (0X0000)

#define BufSize (512)
#define MBAPSize (6)

#define registerListSize (1)

#define numberMaxSize (0XFFFF)
#define numberMinSize (0X0000)
uint16_t NUMBER = 0;

ModbusPDU modebusPDU;


/*封装报文*/
void packModbusTcp(uint16_t functionCode, uint16_t startingAddress, uint16_t quantity, uint8_t unitID, uint16_t* registerList, bool* statusList) {
	

	ModbusPDU::ModbusTcpRequest* UsRequest = (ModbusPDU::ModbusTcpRequest*)malloc(BufSize);//生成的访问命令，这是最终发送给socket的数据   //05 F5 00 00 00 06 01 03 00 00 00 0A
	memset(UsRequest, 0, BufSize);

	UsRequest->MBAPData.transactionMetaIdentifier = NUMBER;							//事件标识符
	UsRequest->MBAPData.protocolIdentifier = MODBUSTCPPROTOCOL;								//ModbusTcp协议
	UsRequest->MBAPData.unitIdentifier = unitID;									//设备ID
	switch (functionCode)//功能码
	{
	//case 1:
	//	UsRequest->functionCode = ModbusPDU::FunctionCode::ReadCoilStatus;
	//	break;
	//case 5:
	//	UsRequest->functionCode = ModbusPDU::FunctionCode::WriteSingleCoil;
	//	break;
	//case 15:
	//	UsRequest->functionCode = ModbusPDU::FunctionCode::WriteMultipleCoil;
	//	break;
	//case 2:
	//	UsRequest->functionCode = ModbusPDU::FunctionCode::ReadInputStatus;
	//	break;
	case 4:
		UsRequest->functionCode = ModbusPDU::FunctionCode::ReadInputRegister;//多个只读
		break;
	case 3:
		UsRequest->functionCode = ModbusPDU::FunctionCode::ReadHoldingRegister;//多个读
		break;
	case 6:
		UsRequest->functionCode = ModbusPDU::FunctionCode::WriteSingleRegister;//单个写
		break;
	case 16:
		UsRequest->functionCode = ModbusPDU::FunctionCode::WriteMultipleRegister;//多个写
		break;
	default:
		UsRequest->functionCode = ModbusPDU::FunctionCode::unKnowFunction;
		break;
	}
	if (UsRequest->functionCode == ModbusPDU::FunctionCode::unKnowFunction) {
		return;
	}
	UsRequest->startingAddress = startingAddress;											//起始地址位						
	UsRequest->quantity = quantity;															//读取多少个地址
	uint8_t commandBytes[BufSize] = {0};
	uint16_t** outLength = (uint16_t**)malloc(1);

	ModbusPDU::InformationCode information = modebusPDU.GenerateReadWriteCommand(UsRequest, statusList, registerList, commandBytes, outLength);//报文封装  返回值：该标识符后的长度
	if (information != ModbusPDU::InformationCode::OK)return;
	UsRequest->MBAPData.MBAPLength = (uint16_t)*outLength;
	NUMBER++;
	if (NUMBER >= numberMaxSize) {
		NUMBER = numberMinSize;
	}

	printf("帧侧请求数据：\t");
	for (int i = 0; i < UsRequest->MBAPData.MBAPLength+ MBAPSize; i++) {
		printf("%02X ", commandBytes[i]);
	}
	printf("\n");
	//free(*outLength);
	free(UsRequest);
}



/*解析报文*/
void unpackModbusTcp(uint16_t functionCode,const char* receivedMessage[], uint16_t startingAddress,int length,uint16_t* outUnpackData) {


	uint8_t* packBuf = 0;
	int j = 0;
	uint8_t InputBuf[BufSize] = { 0 };
	for (int i = 0; i < length; i++) {
		
		receivedMessage[i] = receivedMessage[i + MBAPSize];
		InputBuf[j++] = strtol(receivedMessage[i], NULL, 16);
	}

	packBuf = (uint8_t*)InputBuf;

	//for (int i = 0; i < length; i++)
	//{
	//	printf("%02X ", packBuf[i]);

	//}
	//printf("%d\n", (length - 3) / 2);
	uint16_t quantity = (length - 3) / 2;//读取的对象数量
	bool* statusList = nullptr;//解析出来的读取到的状态对象的数据列表					//对线圈进行的操作（状态对象）
	ModbusPDU::InformationCode information = modebusPDU.TransformClientReceivedData(functionCode,packBuf, quantity, statusList, outUnpackData);//报文解析
	if (information != ModbusPDU::InformationCode::OK) { return; }
	printf("\n");
	for (int i = startingAddress; i < (length - 3) / 2; i++) {
		printf("第%02d个数据：%02d\n", i + 1, outUnpackData[i]);
	}
	

}




int main()
{	
	/*初始化参数*/
	uint16_t functionCode = 0XFF;
	uint16_t startingAddress = 0;
	uint16_t quantity = 0;
	uint8_t unitID = 0;
	bool* statusList = nullptr;//需要往下写的状态量对象数据列表				对线圈进行的操作（状态量对象）
	uint16_t* registerList = nullptr;//需要往下写的寄存器量对象的数据列表		对寄存器进行的操作（寄存器量对象）
	/*初始化参数*/


	/*读取多个保持寄存器的值*/
	/*00 00 00 00 00 06 01 03 00 00 00 0A*/
	functionCode = 3;
	startingAddress = 0;
	quantity = 10;
	unitID = 1;
	packModbusTcp(functionCode, startingAddress, quantity, unitID, registerList, statusList);//报文封装

	/*写入单个保持寄存器*/
	/*00 00 00 00 00 06 01 06 00 00 00 0A*/
	//functionCode = 6;
	//startingAddress = 0;
	//unitID = 1;
	//registerList = (uint16_t*)malloc(registerListSize);
	//registerList = (uint16_t*)0XAAAA;//向从机设备的0000地址上写入000A
	//packModbusTcp(functionCode, startingAddress, quantity, unitID, registerList, statusList);//报文封装




	/*socket通信*/


	const char* receivedMessage[] = { "00"," 00"," 00"," 00"," 00"," 17"," 01"," 03"," 14"," 00"," 00"," 00"," 00"," 00 ","00"," 00 ",
								"01"," 00"," 00"," 00 ","02 ","00 ","00"," 00"," 00 ","00"," 00"," 00 ","00 " } ;					//socket接收的数据（接收到的信息报文）
	int length = sizeof(receivedMessage) / sizeof(receivedMessage[0]) - MBAPSize;
	printf("响应报文：\t");
	for (int i = 0; i < sizeof(receivedMessage) / sizeof(receivedMessage[0]); i++)
	{
		printf("%02X ", strtol(receivedMessage[i], NULL, 16));

	}
	uint16_t* outUnpackData = (uint16_t*)malloc(BufSize);
	//memset(outUnpackData, 0, sizeof(BufSize));
	unpackModbusTcp(functionCode,receivedMessage, startingAddress,length, outUnpackData);//报文解析




	free(outUnpackData);

	/*socket通信*/


	return 0;
}

